#include <iostream>

#include <SDL.h>

#include "Core.h"
#include "Assignment2.h"

#include "Level.h"
#include "Ball.h"
//#include "InputControl.h"

using namespace pong;

static Core* c;

void Assignment2::load(Core& core) {
    c = &core;

    OgreState::load(core);
    BulletState::load(core);

    SDLNet_Init();

    // If we're the guest player ,try to connect to the server
    const char* const serverName = core.serverName();
    const Uint16 serverPort = core.serverPort();
    if (serverName) {
        IPaddress p2Addr;
        if (SDLNet_ResolveHost(&p2Addr, serverName, serverPort) < 0) {
            std::cout << "Failed to resolve "
                      << serverName << ':' << serverPort << std::endl;
            core.halt();
            return;
        }

        clientSock = SDLNet_TCP_Open(&p2Addr);
        if (!clientSock) {
            std::cout << "Failed to connect to "
                      << serverName << ':' << serverPort << std::endl;
            core.halt();
            return;
        }

        IPaddress peerAddr;
        SDLNet_TCP_GetPeerAddress(clientSock);

        std::cout << "Connection from" << peerAddr.host << ':' << peerAddr.port
                  << std::endl;
    } else {
        IPaddress ip;
        /* Resolving the host using NULL make network interface to listen */
        if (SDLNet_ResolveHost(&ip, NULL, 2000) < 0) {
            std::cout << "Failed resolve server address!" << std::endl;
            core.halt();
        }

        /* Open a connection with the IP provided (listen on the host's port) */
        if (!(serverSock = SDLNet_TCP_Open(&ip))) {
            std::cout << "Failed to open server socket" << std::endl;
            core.halt();
        }

        std::cout << "Waiting for other player..." << std::endl;
        while (!clientSock)
            clientSock = SDLNet_TCP_Accept(serverSock);

        IPaddress peerAddr;
        SDLNet_TCP_GetPeerAddress(clientSock);

        std::cout << "Connection from" << peerAddr.host << ':' << peerAddr.port
                  << std::endl;
    }

    world->setGravity(btVector3(0, -10, 0));

    Level box(Ogre::AxisAlignedBox(-50, -50, -70, 50, 50, 70));

    box.render(sceneMan->getRootSceneNode());

    sceneMan->setAmbientLight(Ogre::ColourValue(0.05f, 0.05f, 0.05f));

    Ogre::Light* l = sceneMan->createLight("MainLight");

    l->setDiffuseColour(.5f, 0.2f, 0);
    l->setSpecularColour(Ogre::ColourValue::White);
    //l->setAttenuation(box.boundaries().getSize()., 1, 0, .1f);
    l->setPosition(15,15,15);

    Ogre::SceneNode* const camNode =
        sceneMan->getRootSceneNode()->createChildSceneNode();

    camNode->attachObject(cam);
    camNode->translate(0, 0, 200);
    camNode->lookAt(Ogre::Vector3::ZERO, Ogre::Node::TS_WORLD);

    //Controller c(camNode, ogreRoot, keys, mouse);

    ball = new Ball(core, sceneMan->getRootSceneNode(), 0, 1, world);
}

void Assignment2::unload(Core& core) {
    delete ball;

    if (serverSock) SDLNet_TCP_Close(serverSock);
    if (clientSock) SDLNet_TCP_Close(clientSock);
    SDLNet_Quit();

    BulletState::unload(core);
    OgreState::unload(core);
}

bool Assignment2::keyPressed(const OIS::KeyEvent& e) {
    if (e.key == OIS::KC_ESCAPE) {
        c->halt();
    }
    return true;
}
